/*
 * VisualizerView.java
 */

package dipl.visualizer.ui;

import dipl.algorithm.impl.Intersection;
import dipl.algorithm.impl.Parameters;
import dipl.algorithm.impl.ScmpAlgorithmBezier;
import dipl.visualizer.algorithm.ScmpAlgorithmBezierStepwise;
import dipl.algorithm.math.curve.BezierCurve;
import dipl.algorithm.math.geometry.ConvexHull2d;
import dipl.algorithm.math.geometry.op.ConvexPolygons2d;
import dipl.algorithm.math.utility.FPMath;
import dipl.algorithm.math.primitive.Point2d;
import dipl.algorithm.math.primitive.Tuple2;
import dipl.algorithm.math.fp.primitive.Point2df;
import dipl.algorithm.utility.convert.ApfloatConversion;
import dipl.algorithm.utility.text.CodeGeneration;
import dipl.algorithm.math.fp.primitive.Matrix3x3f;
import dipl.algorithm.math.fp.primitive.op.AffineTransformations2d;
import dipl.algorithm.math.geometry.BoundingWedge2d;
import dipl.algorithm.math.geometry.op.Point2dSetOps;
import dipl.algorithm.math.utility.BezierCurveFactory;
import dipl.algorithm.math.utility.Point2dSetFactory;
import dipl.algorithm.math.utility.ApfloatUtils;
import dipl.visualizer.graphics.ColorOps;
import dipl.visualizer.graphics.shape.BezierCurveShape;
import dipl.visualizer.graphics.shape.BoundingWedge2dShape;
import dipl.visualizer.graphics.shape.LineSegmentShape;
import dipl.visualizer.graphics.shape.Polygon2dShape;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.Random;
import javax.swing.DefaultListModel;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import org.apfloat.Apfloat;

/**
 * The application's main frame.
 */
public class VisualizerView extends FrameView {

    public VisualizerView(SingleFrameApplication app) {
			super(app);

			initComponents();
			this.getFrame().setState( Frame.MAXIMIZED_BOTH );

			// status bar initialization - message timeout, idle icon and busy animation, etc
			ResourceMap resourceMap = getResourceMap();
			int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
			messageTimer = new Timer(messageTimeout, new ActionListener() {
					public void actionPerformed(ActionEvent e) {
							statusMessageLabel.setText("");
					}
			});
			messageTimer.setRepeats(false);
			int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
			for (int i = 0; i < busyIcons.length; i++) {
					busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
			}
			busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {
					public void actionPerformed(ActionEvent e) {
							busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
							statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
					}
			});
			idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
			statusAnimationLabel.setIcon(idleIcon);
			progressBar.setVisible(false);

			// connecting action tasks to status bar via TaskMonitor
			TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
			taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
					public void propertyChange(java.beans.PropertyChangeEvent evt) {
							String propertyName = evt.getPropertyName();
							if ("started".equals(propertyName)) {
									if (!busyIconTimer.isRunning()) {
											statusAnimationLabel.setIcon(busyIcons[0]);
											busyIconIndex = 0;
											busyIconTimer.start();
									}
									progressBar.setVisible(true);
									progressBar.setIndeterminate(true);
							} else if ("done".equals(propertyName)) {
									busyIconTimer.stop();
									statusAnimationLabel.setIcon(idleIcon);
									progressBar.setVisible(false);
									progressBar.setValue(0);
							} else if ("message".equals(propertyName)) {
									String text = (String)(evt.getNewValue());
									statusMessageLabel.setText((text == null) ? "" : text);
									messageTimer.restart();
							} else if ("progress".equals(propertyName)) {
									int value = (Integer)(evt.getNewValue());
									progressBar.setVisible(true);
									progressBar.setIndeterminate(false);
									progressBar.setValue(value);
							}
					}
			});
			
			this.algorithmSplineStep = new ScmpAlgorithmBezierStepwise(
				this.shapeViewer,
				(DefaultListModel)this.listCandStack.getModel(),
				this.messages );
      this.algorithmSpline = new ScmpAlgorithmBezier();
			this.algorithmEigenwilligAP = new dipl.algorithm.impl.ScmpAlgorithmBezierRootIsolation();
			this.algorithmEigenwilligFP = new dipl.algorithm.impl.fp.ScmpAlgorithmBezierRootIsolation();
			
			this.algoTreshold = new Apfloat( 1e-6 ).toRadix( ApfloatUtils.radix );
			this.L = 5;
			
			OnInitialized();
		}

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = VisualizerApp.getApplication().getMainFrame();
            aboutBox = new VisualizerAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        VisualizerApp.getApplication().show(aboutBox);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    mainPanel = new javax.swing.JPanel();
    splitPaneMain = new javax.swing.JSplitPane();
    splitPaneLeft = new javax.swing.JSplitPane();
    labelState = new javax.swing.JLabel();
    shapeViewer = new dipl.visualizer.ui.ShapeViewer();
    splitPaneRight = new javax.swing.JSplitPane();
    jScrollPane2 = new javax.swing.JScrollPane();
    messages = new javax.swing.JTextArea();
    jSplitPane1 = new javax.swing.JSplitPane();
    jLabel1 = new javax.swing.JLabel();
    jScrollPane1 = new javax.swing.JScrollPane();
    listCandStack = new javax.swing.JList();
    menuBar = new javax.swing.JMenuBar();
    javax.swing.JMenu fileMenu = new javax.swing.JMenu();
    javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
    menuView = new javax.swing.JMenu();
    miZoomIn = new javax.swing.JMenuItem();
    miZoomOut = new javax.swing.JMenuItem();
    miClearMsg = new javax.swing.JMenuItem();
    menuData = new javax.swing.JMenu();
    menuData2Curves = new javax.swing.JMenu();
    jMenuItem4 = new javax.swing.JMenuItem();
    jMenuItem2 = new javax.swing.JMenuItem();
    miBernstein = new javax.swing.JMenuItem();
    jMenuItem5 = new javax.swing.JMenuItem();
    menuDataOther = new javax.swing.JMenu();
    jMenuItem1 = new javax.swing.JMenuItem();
    jMenuItem6 = new javax.swing.JMenuItem();
    menuAlgorithm = new javax.swing.JMenu();
    jSeparator1 = new javax.swing.JSeparator();
    miAlgoSpline = new javax.swing.JMenuItem();
    miAlgoEigenwillig = new javax.swing.JMenuItem();
    miAlgoEigenwilligFP = new javax.swing.JMenuItem();
    jSeparator3 = new javax.swing.JSeparator();
    meAlgoStepwise = new javax.swing.JMenu();
    miRestartStep = new javax.swing.JMenuItem();
    miProceedStep = new javax.swing.JMenuItem();
    checkEnableYap = new javax.swing.JMenu();
    checkEnableStatistics = new javax.swing.JCheckBoxMenuItem();
    checkEnableSP = new javax.swing.JCheckBoxMenuItem();
    miYap = new javax.swing.JCheckBoxMenuItem();
    jMenuItem3 = new javax.swing.JMenuItem();
    javax.swing.JMenu helpMenu = new javax.swing.JMenu();
    javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
    jMenuItem7 = new javax.swing.JMenuItem();
    statusPanel = new javax.swing.JPanel();
    javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
    statusMessageLabel = new javax.swing.JLabel();
    statusAnimationLabel = new javax.swing.JLabel();
    progressBar = new javax.swing.JProgressBar();

    mainPanel.setName("mainPanel"); // NOI18N

    splitPaneMain.setBorder(null);
    splitPaneMain.setDividerLocation(300);
    splitPaneMain.setDividerSize(2);
    splitPaneMain.setResizeWeight(1.0);
    splitPaneMain.setName("splitPane"); // NOI18N

    splitPaneLeft.setBorder(null);
    splitPaneLeft.setDividerLocation(30);
    splitPaneLeft.setDividerSize(2);
    splitPaneLeft.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
    splitPaneLeft.setName("splitPaneLeft"); // NOI18N

    org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(dipl.visualizer.ui.VisualizerApp.class).getContext().getResourceMap(VisualizerView.class);
    labelState.setText(resourceMap.getString("labelState.text")); // NOI18N
    labelState.setName("labelState"); // NOI18N
    splitPaneLeft.setLeftComponent(labelState);

    shapeViewer.setName("shapeViewer"); // NOI18N

    javax.swing.GroupLayout shapeViewerLayout = new javax.swing.GroupLayout(shapeViewer);
    shapeViewer.setLayout(shapeViewerLayout);
    shapeViewerLayout.setHorizontalGroup(
      shapeViewerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 300, Short.MAX_VALUE)
    );
    shapeViewerLayout.setVerticalGroup(
      shapeViewerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 517, Short.MAX_VALUE)
    );

    splitPaneLeft.setRightComponent(shapeViewer);

    splitPaneMain.setLeftComponent(splitPaneLeft);

    splitPaneRight.setBorder(null);
    splitPaneRight.setDividerLocation(200);
    splitPaneRight.setDividerSize(2);
    splitPaneRight.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
    splitPaneRight.setName("splitPaneRight"); // NOI18N

    jScrollPane2.setName("jScrollPane2"); // NOI18N

    messages.setBackground(resourceMap.getColor("messages.background")); // NOI18N
    messages.setColumns(20);
    messages.setFont(resourceMap.getFont("messages.font")); // NOI18N
    messages.setForeground(resourceMap.getColor("messages.foreground")); // NOI18N
    messages.setRows(5);
    messages.setToolTipText(resourceMap.getString("messages.toolTipText")); // NOI18N
    messages.setCaretColor(resourceMap.getColor("messages.caretColor")); // NOI18N
    messages.setName("messages"); // NOI18N
    jScrollPane2.setViewportView(messages);

    splitPaneRight.setRightComponent(jScrollPane2);

    jSplitPane1.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
    jSplitPane1.setDividerLocation(20);
    jSplitPane1.setDividerSize(2);
    jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
    jSplitPane1.setName("jSplitPane1"); // NOI18N

    jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
    jLabel1.setName("jLabel1"); // NOI18N
    jSplitPane1.setTopComponent(jLabel1);

    jScrollPane1.setToolTipText(resourceMap.getString("jScrollPane1.toolTipText")); // NOI18N
    jScrollPane1.setName("jScrollPane1"); // NOI18N

    listCandStack.setModel(new DefaultListModel());
    listCandStack.setToolTipText(resourceMap.getString("listCandStack.toolTipText")); // NOI18N
    listCandStack.setName("listCandStack"); // NOI18N
    jScrollPane1.setViewportView(listCandStack);

    jSplitPane1.setRightComponent(jScrollPane1);

    splitPaneRight.setLeftComponent(jSplitPane1);

    splitPaneMain.setRightComponent(splitPaneRight);

    javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
    mainPanel.setLayout(mainPanelLayout);
    mainPanelLayout.setHorizontalGroup(
      mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addComponent(splitPaneMain, javax.swing.GroupLayout.DEFAULT_SIZE, 775, Short.MAX_VALUE)
    );
    mainPanelLayout.setVerticalGroup(
      mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addComponent(splitPaneMain, javax.swing.GroupLayout.DEFAULT_SIZE, 549, Short.MAX_VALUE)
    );

    menuBar.setName("menuBar"); // NOI18N

    fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
    fileMenu.setName("fileMenu"); // NOI18N

    javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(dipl.visualizer.ui.VisualizerApp.class).getContext().getActionMap(VisualizerView.class, this);
    exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
    exitMenuItem.setName("exitMenuItem"); // NOI18N
    fileMenu.add(exitMenuItem);

    menuBar.add(fileMenu);

    menuView.setLabel(resourceMap.getString("menuView.label")); // NOI18N
    menuView.setName("menuView"); // NOI18N

    miZoomIn.setAction(actionMap.get("OnZoomIn")); // NOI18N
    miZoomIn.setLabel(resourceMap.getString("miZoomIn.label")); // NOI18N
    miZoomIn.setName("miZoomIn"); // NOI18N
    menuView.add(miZoomIn);

    miZoomOut.setAction(actionMap.get("OnZoomOut")); // NOI18N
    miZoomOut.setLabel(resourceMap.getString("miZoomOut.label")); // NOI18N
    miZoomOut.setName("miZoomOut"); // NOI18N
    menuView.add(miZoomOut);

    miClearMsg.setAction(actionMap.get("OnClearMessages")); // NOI18N
    miClearMsg.setLabel(resourceMap.getString("miClearMsg.label")); // NOI18N
    miClearMsg.setName("miClearMsg"); // NOI18N
    menuView.add(miClearMsg);

    menuBar.add(menuView);
    menuView.getAccessibleContext().setAccessibleName(resourceMap.getString("jMenu1.AccessibleContext.accessibleName")); // NOI18N

    menuData.setText(resourceMap.getString("menuData.text")); // NOI18N
    menuData.setName("menuData"); // NOI18N

    menuData2Curves.setText(resourceMap.getString("menuData2Curves.text")); // NOI18N
    menuData2Curves.setName("menuData2Curves"); // NOI18N

    jMenuItem4.setAction(actionMap.get("OnRandomCurves")); // NOI18N
    jMenuItem4.setText(resourceMap.getString("jMenuItem4.text")); // NOI18N
    jMenuItem4.setName("jMenuItem4"); // NOI18N
    menuData2Curves.add(jMenuItem4);

    jMenuItem2.setAction(actionMap.get("OnTransversalHardCase")); // NOI18N
    jMenuItem2.setName("jMenuItem2"); // NOI18N
    menuData2Curves.add(jMenuItem2);

    miBernstein.setAction(actionMap.get("OnBernsteinXAxis")); // NOI18N
    miBernstein.setName("miBernstein"); // NOI18N
    menuData2Curves.add(miBernstein);

    jMenuItem5.setAction(actionMap.get("On2CurvesIntersectNonCrossing")); // NOI18N
    jMenuItem5.setName("jMenuItem5"); // NOI18N
    menuData2Curves.add(jMenuItem5);

    menuData.add(menuData2Curves);

    menuDataOther.setText(resourceMap.getString("menuDataOther.text")); // NOI18N
    menuDataOther.setName("menuDataOther"); // NOI18N

    jMenuItem1.setAction(actionMap.get("OnBoundingWedgeBezier")); // NOI18N
    jMenuItem1.setName("jMenuItem1"); // NOI18N
    menuDataOther.add(jMenuItem1);

    jMenuItem6.setAction(actionMap.get("OnConvexUnion")); // NOI18N
    jMenuItem6.setName("jMenuItem6"); // NOI18N
    menuDataOther.add(jMenuItem6);

    menuData.add(menuDataOther);

    menuBar.add(menuData);

    menuAlgorithm.setLabel(resourceMap.getString("menuAlgorithm.label")); // NOI18N
    menuAlgorithm.setName("menuAlgorithm"); // NOI18N

    jSeparator1.setName("jSeparator1"); // NOI18N
    menuAlgorithm.add(jSeparator1);

    miAlgoSpline.setAction(actionMap.get("OnAlgorithmSpline")); // NOI18N
    miAlgoSpline.setText(resourceMap.getString("miAlgoSpline.text")); // NOI18N
    miAlgoSpline.setActionCommand(resourceMap.getString("miAlgoSpline.actionCommand")); // NOI18N
    miAlgoSpline.setName("miAlgoSpline"); // NOI18N
    menuAlgorithm.add(miAlgoSpline);

    miAlgoEigenwillig.setAction(actionMap.get("OnAlgorithmEigenwillig")); // NOI18N
    miAlgoEigenwillig.setText(resourceMap.getString("miAlgoEigenwillig.text")); // NOI18N
    miAlgoEigenwillig.setActionCommand(resourceMap.getString("miAlgoEigenwillig.actionCommand")); // NOI18N
    miAlgoEigenwillig.setAutoscrolls(true);
    miAlgoEigenwillig.setName("miAlgoEigenwillig"); // NOI18N
    menuAlgorithm.add(miAlgoEigenwillig);

    miAlgoEigenwilligFP.setAction(actionMap.get("OnAlgorithmEigenwilligFP")); // NOI18N
    miAlgoEigenwilligFP.setName("miAlgoEigenwilligFP"); // NOI18N
    menuAlgorithm.add(miAlgoEigenwilligFP);

    jSeparator3.setName("jSeparator3"); // NOI18N
    menuAlgorithm.add(jSeparator3);

    meAlgoStepwise.setText(resourceMap.getString("meAlgoStepwise.text")); // NOI18N
    meAlgoStepwise.setName("meAlgoStepwise"); // NOI18N

    miRestartStep.setAction(actionMap.get("OnAlgorithmStepRestart")); // NOI18N
    miRestartStep.setName("miRestartStep"); // NOI18N
    meAlgoStepwise.add(miRestartStep);

    miProceedStep.setAction(actionMap.get("OnAlgorithmStepProceed")); // NOI18N
    miProceedStep.setName("miProceedStep"); // NOI18N
    meAlgoStepwise.add(miProceedStep);

    menuAlgorithm.add(meAlgoStepwise);

    menuBar.add(menuAlgorithm);

    checkEnableYap.setText(resourceMap.getString("checkEnableYap.text")); // NOI18N
    checkEnableYap.setName("checkEnableYap"); // NOI18N

    checkEnableStatistics.setSelected(true);
    checkEnableStatistics.setText(resourceMap.getString("checkEnableStatistics.text")); // NOI18N
    checkEnableStatistics.setName("checkEnableStatistics"); // NOI18N
    checkEnableYap.add(checkEnableStatistics);

    checkEnableSP.setSelected(true);
    checkEnableSP.setText(resourceMap.getString("checkEnableSP.text")); // NOI18N
    checkEnableSP.setActionCommand(resourceMap.getString("checkEnableSP.actionCommand")); // NOI18N
    checkEnableSP.setName("checkEnableSP"); // NOI18N
    checkEnableYap.add(checkEnableSP);

    miYap.setSelected(true);
    miYap.setText(resourceMap.getString("miYap.text")); // NOI18N
    miYap.setName("miYap"); // NOI18N
    checkEnableYap.add(miYap);

    jMenuItem3.setAction(actionMap.get("OnShowOptions")); // NOI18N
    jMenuItem3.setName("jMenuItem3"); // NOI18N
    checkEnableYap.add(jMenuItem3);

    menuBar.add(checkEnableYap);

    helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
    helpMenu.setName("helpMenu"); // NOI18N

    aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
    aboutMenuItem.setName("aboutMenuItem"); // NOI18N
    helpMenu.add(aboutMenuItem);

    jMenuItem7.setAction(actionMap.get("ShowUsageBox")); // NOI18N
    jMenuItem7.setText(resourceMap.getString("jMenuItem7.text")); // NOI18N
    jMenuItem7.setName("jMenuItem7"); // NOI18N
    helpMenu.add(jMenuItem7);

    menuBar.add(helpMenu);

    statusPanel.setName("statusPanel"); // NOI18N

    statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

    statusMessageLabel.setName("statusMessageLabel"); // NOI18N

    statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
    statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

    progressBar.setName("progressBar"); // NOI18N

    javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
    statusPanel.setLayout(statusPanelLayout);
    statusPanelLayout.setHorizontalGroup(
      statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addComponent(statusPanelSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 775, Short.MAX_VALUE)
      .addGroup(statusPanelLayout.createSequentialGroup()
        .addContainerGap()
        .addComponent(statusMessageLabel)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 605, Short.MAX_VALUE)
        .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(statusAnimationLabel)
        .addContainerGap())
    );
    statusPanelLayout.setVerticalGroup(
      statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(statusPanelLayout.createSequentialGroup()
        .addComponent(statusPanelSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(statusMessageLabel)
          .addComponent(statusAnimationLabel)
          .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addGap(3, 3, 3))
    );

    setComponent(mainPanel);
    setMenuBar(menuBar);
    setStatusBar(statusPanel);
  }// </editor-fold>//GEN-END:initComponents

	//
	// AUXILLIARY METHODS
	//

	/**
	 * @return currently enabled algorithm parameters
	 */
	private int GetParameters() {
		int parameters = 0;
		if( checkEnableSP.isSelected() ) parameters |= Parameters.SUPERCOMPOSITION;
		if( checkEnableStatistics.isSelected() ) parameters |= Parameters.COLLECT_DATA;
		if( checkEnableYap.isSelected() ) parameters |= Parameters.BOUNDS_YAP;
		return parameters;
	}

	/// <summary>
	/// prints message to message log.
	/// </summary>
	/// <param name="msg"></param>
	private void PrintMsg( String msg ) {
		messages.append( msg );
	}

	/// <summary>
	/// prints message to message log appending a line break to it.
	/// </summary>
	/// <param name="msg"></param>
	private void PrintMsgLine( String msg ) {
		messages.append( msg+"\n" );
	}

	/// <summary>
	/// Starts stepwise algorithm with given two bezier curves as input
	/// </summary>
	/// <param name="f"></param>
	/// <param name="g"></param>
	private void StartStepwiseAlgorithm( BezierCurve f, BezierCurve g ) {
		miRestartStep.setEnabled( true );
		miProceedStep.setEnabled( true );
		miAlgoSpline.setEnabled( true );

		PrintMsg( CodeGeneration.Point2dArrayString( "controls_f", ApfloatConversion.ConvertPoints( f.Controls() ) ) );
		PrintMsg( CodeGeneration.Point2dArrayString( "controls_g", ApfloatConversion.ConvertPoints( g.Controls() ) ) );
		PrintMsgLine( Point2dSetOps.ToArgString( f.Controls() ) );
		PrintMsgLine( Point2dSetOps.ToArgString( g.Controls() ) );
		try {
			algorithmSplineStep.Start( f, g, GetParameters()|Parameters.LOG, algoTreshold, L );
		}
		catch( Exception e ) {
			e.printStackTrace();
		}
		labelState.setText( "Current state: "+algorithmSplineStep.CurrentStateString() );
	}

	//
	// EVENT HANDLER
	//

	@Action
	public void OnZoomIn() {
		this.shapeViewer.ZoomBy( 0.1, 0.1 );
	}

	@Action
	public void OnZoomOut() {
		this.shapeViewer.ZoomBy( -0.1, -0.1 );
	}

	@Action
	public void OnClearMessages() {
		this.messages.setText( "" );
	}

	@Action
	public void OnAlgorithmStepRestart() {
		try {
			algorithmSplineStep.Start( input[0], input[1], GetParameters()|Parameters.LOG, algoTreshold, L );
		}
		catch( Exception e ) {
			e.printStackTrace();
		}
		miProceedStep.setEnabled( true );
	}

	@Action
	public void OnAlgorithmStepProceed() {
		try {
			algorithmSplineStep.Proceed();
		}
		catch( Exception e ) {
			e.printStackTrace();
		}
		miProceedStep.setEnabled( !algorithmSplineStep.Finished() );
		labelState.setText( "Current state: "+algorithmSplineStep.CurrentStateString() );
	}

	@Action
	public void OnAlgorithmSpline() {
		Iterator<Intersection> res = null;
		try {
			algorithmSpline.CalculateIntersections( input[0], input[1], GetParameters(), algoTreshold, L );
			res = algorithmSpline.Intersections();
		}
		catch( Exception e ) {
			e.printStackTrace();
			return;
		}
		PrintMsgLine( "\nDirect-Algorithm delivered following results:" );
		if( res.hasNext() == false ) {
			PrintMsgLine( "None." );
		}
		else {
			while( res.hasNext() ) {
				PrintMsgLine( res.next().toString() );
			}
		}
		PrintMsgLine( "Statistics:\n"+algorithmSpline.Statistics().toString() );
	}

	@Action
	public void OnRandomCurves() {
		this.shapeViewer.SetCoordinateSystem( -(1<<L), 1<<L, -(1<<L), 1<<L );
		this.input = new BezierCurve[2];
		Random rand = new Random();
		input[0] = BezierCurveFactory.CreateRandomLBitCoeff( rand, 3, 8, L );
		input[1] = BezierCurveFactory.CreateRandomLBitCoeff( rand, 3, 8, L );
		PrintMsgLine( "Generated random curves with ("+L+","+L+")-bit float coefficients." );
		StartStepwiseAlgorithm( input[0], input[1] );
		this.miAlgoSpline.setEnabled( true );
		this.meAlgoStepwise.setEnabled( true );
		this.miAlgoEigenwillig.setEnabled( false );
		this.miAlgoEigenwilligFP.setEnabled( false );
	}

	@Action
	public void OnBoundingWedgeBezier() {
		Random rand = new Random();

		this.miAlgoSpline.setEnabled( false );
		this.meAlgoStepwise.setEnabled( false );
		this.miAlgoEigenwillig.setEnabled( false );
		this.miAlgoEigenwilligFP.setEnabled( false );

		this.shapeViewer.SetCoordinateSystem( -6, 6, -6, 6 );
		this.shapeViewer.Clear();

		FPMath fpMath = new FPMath( 48 );
		BezierCurve curve = BezierCurveFactory.CreateRandom( rand, 4, 9, 1.0, 1.0, 2.0, 2.0 );
		BoundingWedge2d wedge = curve.BoundingWedge( fpMath );
		Font font = getComponent().getFont();
		try {
			this.shapeViewer.AddShape( new BezierCurveShape( fpMath, "curve", curve, 64, Color.green, font, true ) );
			BezierCurve hodograph = curve.Hodograph( fpMath, true );
			this.shapeViewer.AddShape( new BezierCurveShape( fpMath, "hodograph", hodograph, 64, Color.red, font, true ) );
			for( int i= 0; i < hodograph.Controls().length; i++ ) {
				this.shapeViewer.AddShape( 
					new LineSegmentShape( "",
						new Point2df( 0.0, 0.0 ),
						ApfloatConversion.ConvertPoint( hodograph.Controls()[i] ), Color.blue
					)
				);
			}
			PrintMsg( CodeGeneration.Point2dArrayString( "controls", ApfloatConversion.ConvertPoints( curve.Controls() ) ) );
			this.shapeViewer.AddShape(
				new BoundingWedge2dShape( "c1",
					new Point2df( 0.0, 0.0 ),
					wedge,
					Color.blue,
					ColorOps.FromArgb( 64, Color.blue ),
					true,
					font
				)
			);
		}
		catch( Exception e ) {
			e.printStackTrace();
		}
		PrintMsgLine( wedge.toString() );
		this.shapeViewer.Flush();
	}

	/**
	 * Is called after main frame is initialized
	 */
	protected void OnInitialized() {
	}

	@Action
	public void OnAlgorithmParamLog() {
	}

	@Action
	public void OnTransversalHardCase() {
		// construct a hard case of transversal crossing where the
		// intersection point on f lies near t=0.5
		Random rand = new Random();
		// generate random control polygon of degree 3
		Point2df[] controls_f = new Point2df[4];
		controls_f[0] = new Point2df( -1.0+rand.nextDouble(), -1.0+rand.nextDouble() );
		controls_f[1] = new Point2df( -0.5, 0+0.1*rand.nextDouble() );
		controls_f[2] = new Point2df( 0.5, -controls_f[1].y );
		controls_f[3] = new Point2df( -controls_f[0].x, -controls_f[0].y );
		// controls of second curve are rotated versions of first one
		Point2df[] controls_g = new Point2df[controls_f.length];
		Matrix3x3f mRot		= AffineTransformations2d.Rotation( 0.7*Math.PI/2.0 );
		Matrix3x3f mScale	=	AffineTransformations2d.Scaling( 0.6, 0.6 );
		//Matrix3x3_f mTrans	=	AffineTransformations2d_f.Translation( 0.001, 0.001 );
		for( int i = 0; i < controls_f.length; i++ ) {
			controls_g[i] = AffineTransformations2d.Transform( mRot, controls_f[i] );
			AffineTransformations2d.TransformPoint( mScale, controls_g[i] );
			//AffineTransformations2d_f.TransformPoint( mTrans, controls_g[i] );
		}
		try {
			input = new BezierCurve[2];
			input[0] = new BezierCurve( ApfloatConversion.ConvertPoints( controls_f ) );
			input[1] = new BezierCurve( ApfloatConversion.ConvertPoints( controls_g ) );
			StartStepwiseAlgorithm( input[0], input[1] );
		}
		catch( Exception e ) {
			e.printStackTrace();
			return;
		}
		
	}

	@Action
	public void OnAlgorithmEigenwillig() {
		Iterator<Intersection> res = null;
		try {
			algorithmEigenwilligAP.CalculateIntersections( input[0], GetParameters(), algoTreshold, L );
			res = algorithmEigenwilligAP.Intersections();
		}
		catch( Exception e ) {
			e.printStackTrace();
			return;
		}
		PrintMsgLine( "\nRoot-isolation-algorithm delivered following results:" );
		if( res.hasNext() == false ) {
			PrintMsgLine( "None." );
		}
		else {
			while( res.hasNext() ) {
				PrintMsgLine( res.next().toString() );
			}
		}
		PrintMsgLine( "Statistics:\n"+algorithmEigenwilligAP.Statistics().toString() );
	}

	@Action
	public void OnBernsteinXAxis() {
		this.miAlgoSpline.setEnabled( true );
		this.meAlgoStepwise.setEnabled( true );
		this.miAlgoEigenwillig.setEnabled( true );
		this.miAlgoEigenwilligFP.setEnabled( true );

		input = new BezierCurve[2];
/*
Point2df[] c = new Point2df[] {
  new Point2df( 0.0, -0.9936286777818186 ),
  new Point2df( 0.19999999999999998, 0.1125339434070384 ),
  new Point2df( 0.39999999999999997, 0.9515902587644345 ),
  new Point2df( 0.6000000000000001, -0.7164616658787604 ),
  new Point2df( 0.8, 0.0871582994326594 ),
  new Point2df( 1.0, 0.24675664201506659 ),
};*/
try {
			//input[0] = new BezierCurve( ApfloatConversion.ConvertPoints( c ) );

			Random rand = new Random();
			input[0] = BezierCurveFactory.CreateRandomBernsteinPolynomialIC( rand, 6, -3, -5,5 );
			input[1] = new BezierCurve(
        new Point2d[] {
          new Point2d( input[0].Controls()[0].x, ApfloatUtils._0 ),
          new Point2d( input[0].Controls()[input[0].Degree()].x, ApfloatUtils._0 ),
        }
      );
			StartStepwiseAlgorithm( input[0], input[1] );
			this.shapeViewer.SetCoordinateSystem( -5, 5, -5, 5 );
	}
		catch( Exception e ) {
			e.printStackTrace();
		}
	}

	@Action
	public void On2CurvesIntersectNonCrossing() {
		Random rand = new Random();
		input = new BezierCurve[2];
		FPMath fpMath = new FPMath( 48 );
		try {
			input[0] = BezierCurveFactory.CreateRandom( rand, 3, 8 );
			// in order to optain one point of tangential touching we subdivide generated
			// random curve. The subdivision point will become the touching point.
			Tuple2<BezierCurve,BezierCurve> subc = null;
			subc = input[0].Subdivide( fpMath, ApfloatUtils.ValueOf( 0.5 ) );
			// construct second curve
			Point2df[] controls = new Point2df[3];
			controls[0] = ApfloatConversion.ConvertPoint( subc.fst.Controls()[subc.fst.Controls().length-2] );
			controls[1] = ApfloatConversion.ConvertPoint( subc.snd.Controls()[0] );
			controls[2] = ApfloatConversion.ConvertPoint( subc.snd.Controls()[1] );
			input[1] = new BezierCurve( ApfloatConversion.ConvertPoints( controls ) );
			StartStepwiseAlgorithm( input[0], input[1] );
		}
		catch( Exception e ) {
			e.printStackTrace();
			return;
		}
	}

	@Action
	public void OnShowOptions() {
		OptionsDialog dlg = new OptionsDialog( this.getFrame(), true );
		dlg.SetL( L );
		dlg.setVisible(true);
		L = dlg.L() <= 0 ? 1 : dlg.L();
	}

	@Action
	public void OnConvexUnion() {
		Random rand = new Random();

		this.miAlgoSpline.setEnabled( false );
		this.meAlgoStepwise.setEnabled( false );
		this.miAlgoEigenwillig.setEnabled( false );
		this.miAlgoEigenwilligFP.setEnabled( false );

		this.shapeViewer.SetCoordinateSystem( -4, 4, -4, 4 );
		this.shapeViewer.Clear();

		FPMath fpMath = new FPMath( 48 );
		Point2d[] p1 = Point2dSetFactory.CreateRandom( rand, 1+(int)(rand.nextDouble()*20.0) );
		Point2d[] p2 = Point2dSetFactory.CreateRandom( rand, 1+(int)(rand.nextDouble()*20.0) );
		ConvexHull2d h1 = new ConvexHull2d( fpMath, p1 );
		ConvexHull2d h2 = new ConvexHull2d( fpMath, p2 );
		ConvexHull2d u = ConvexPolygons2d.Union( h1, h2 );

		try {
			shapeViewer.AddShape( new Polygon2dShape( "h1", h1.Vertices(), Color.blue ) );
			shapeViewer.AddShape( new Polygon2dShape( "h2", h2.Vertices(), Color.red ) );
			shapeViewer.AddShape( new Polygon2dShape( "u", u.Vertices(), Color.yellow ) );
		}
		catch( Exception e ) {
			e.printStackTrace();
		}
		this.shapeViewer.Flush();
	}

	@Action
	public void OnAlgorithmEigenwilligFP() {
		Iterator<dipl.algorithm.impl.fp.Intersection> res = null;
		try {
			dipl.algorithm.math.fp.curve.BezierCurve c0 = new dipl.algorithm.math.fp.curve.BezierCurve(
				ApfloatConversion.ConvertPoints( input[0].Controls() ) );
			algorithmEigenwilligFP.CalculateIntersections( c0, GetParameters(), algoTreshold.doubleValue() );
			res = algorithmEigenwilligFP.Intersections();
		}
		catch( Exception e ) {
			e.printStackTrace();
			return;
		}
		PrintMsgLine( "\nRoot-isolation-algorithm delivered following results:" );
		if( res.hasNext() == false ) {
			PrintMsgLine( "None." );
		}
		else {
			while( res.hasNext() ) {
				PrintMsgLine( res.next().toString() );
			}
		}
		PrintMsgLine( "Statistics:\n"+algorithmEigenwilligFP.Statistics().toString() );
	}

	@Action
	public void ShowUsageBox() {
		UsageDialog dlg = new UsageDialog( this.getFrame(), true );
		dlg.setVisible( true );
	}

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JCheckBoxMenuItem checkEnableSP;
  private javax.swing.JCheckBoxMenuItem checkEnableStatistics;
  private javax.swing.JMenu checkEnableYap;
  private javax.swing.JLabel jLabel1;
  private javax.swing.JMenuItem jMenuItem1;
  private javax.swing.JMenuItem jMenuItem2;
  private javax.swing.JMenuItem jMenuItem3;
  private javax.swing.JMenuItem jMenuItem4;
  private javax.swing.JMenuItem jMenuItem5;
  private javax.swing.JMenuItem jMenuItem6;
  private javax.swing.JMenuItem jMenuItem7;
  private javax.swing.JScrollPane jScrollPane1;
  private javax.swing.JScrollPane jScrollPane2;
  private javax.swing.JSeparator jSeparator1;
  private javax.swing.JSeparator jSeparator3;
  private javax.swing.JSplitPane jSplitPane1;
  private javax.swing.JLabel labelState;
  private javax.swing.JList listCandStack;
  private javax.swing.JPanel mainPanel;
  private javax.swing.JMenu meAlgoStepwise;
  private javax.swing.JMenu menuAlgorithm;
  private javax.swing.JMenuBar menuBar;
  private javax.swing.JMenu menuData;
  private javax.swing.JMenu menuData2Curves;
  private javax.swing.JMenu menuDataOther;
  private javax.swing.JMenu menuView;
  private javax.swing.JTextArea messages;
  private javax.swing.JMenuItem miAlgoEigenwillig;
  private javax.swing.JMenuItem miAlgoEigenwilligFP;
  private javax.swing.JMenuItem miAlgoSpline;
  private javax.swing.JMenuItem miBernstein;
  private javax.swing.JMenuItem miClearMsg;
  private javax.swing.JMenuItem miProceedStep;
  private javax.swing.JMenuItem miRestartStep;
  private javax.swing.JCheckBoxMenuItem miYap;
  private javax.swing.JMenuItem miZoomIn;
  private javax.swing.JMenuItem miZoomOut;
  private javax.swing.JProgressBar progressBar;
  private dipl.visualizer.ui.ShapeViewer shapeViewer;
  private javax.swing.JSplitPane splitPaneLeft;
  private javax.swing.JSplitPane splitPaneMain;
  private javax.swing.JSplitPane splitPaneRight;
  private javax.swing.JLabel statusAnimationLabel;
  private javax.swing.JLabel statusMessageLabel;
  private javax.swing.JPanel statusPanel;
  // End of variables declaration//GEN-END:variables

	private final Timer messageTimer;
	private final Timer busyIconTimer;
	private final Icon idleIcon;
	private final Icon[] busyIcons = new Icon[15];
	private int busyIconIndex = 0;

	private JDialog aboutBox;

	/**
	 * spline algorithm
	 */
	private ScmpAlgorithmBezier algorithmSpline;

	/**
	 * stepwise spline algorithm
	 */
	private ScmpAlgorithmBezierStepwise algorithmSplineStep;

	/**
	 * eigentwillig root isolation
	 */
	private dipl.algorithm.impl.ScmpAlgorithmBezierRootIsolation algorithmEigenwilligAP;
	/**
	 * eigentwillig root isolation (fixed precision)
	 */
	private dipl.algorithm.impl.fp.ScmpAlgorithmBezierRootIsolation algorithmEigenwilligFP;

	/**
	 * input curves for algorithm
	 */
	private BezierCurve[] input;

	/**
	 * minimum length of curve segments in algorithm
	 */
	private Apfloat algoTreshold;

	/**
	 * constant for generating (L,L)-bit floats as input
	 */
	private int L;
}
